package cn.xorange.commons.datasource.annotation.aspect;


import cn.xorange.commons.datasource.annotation.DS;
import cn.xorange.commons.datasource.configuration.DSConfig;
import cn.xorange.commons.datasource.constants.DataSourceContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.aop.support.AopUtils;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * @author : yangjian
 * @description : 动态方式去切换数据源
 */
@Slf4j
@Aspect
@Component
@Order(-1)
public class DynamicDSAspect {

    @Resource
    DSConfig dataSourceConfig;

    private boolean dsSwitch = false;

    @Pointcut("@annotation(cn.xorange.commons.datasource.annotation.DS)"
        + "|| @within(cn.xorange.commons.datasource.annotation.DS)")
    private void dsPointCut(){// ds注解切面
    }

    @Around("dsPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {

        DS dataSource = getDataSource(point);
        if (Objects.nonNull(dataSource)) {
            this.dataSourceConfig.isExistDs(dataSource.value());
            log.debug("切换数据源：{}->{}", DataSourceContextHolder.getDataSourceKey(), dataSource.value());
            DataSourceContextHolder.setDataSourceKey(dataSource.value());
        }
        try {
            return point.proceed();
        }
        finally {
            // 销毁数据源 在执行方法之后
            DataSourceContextHolder.clearDataSourceKey();
            dsSwitch = false;
            log.debug("清除数据源");
        }
    }


    /**
     * 获取需要切换的数据源
     */
    private DS getDataSource(ProceedingJoinPoint point) {
        MethodSignature signature = (MethodSignature) point.getSignature();
        DS dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DS.class);
        if (Objects.nonNull(dataSource))
        {
            return dataSource;
        }else {
            return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DS.class);
        }
    }

    ////                             [包路径].[类(全部为*)].[方法](参数[所有..])
    //@Pointcut(value = "execution(* *.mapper.*.*(..))")
    //private void baseMapperPointCut() {// 直接调用baseMapper方法， 防止service 层没有ds注解，会数据源会切换不到
    //}
    //@Around("baseMapperPointCut()")
    //public Object aroundBaseMapper(ProceedingJoinPoint joinPoint) throws Throwable {
    //    if (!dsSwitch){
    //        //获取当前类上的注解
    //        DS dataSource = (DS) ((Class) AopUtils.getTargetClass(joinPoint.getTarget()).getGenericInterfaces()[0]).getAnnotation(DS.class);
    //        if (Objects.nonNull(dataSource)) {
    //            if (dataSource.value().equals(this.dataSourceConfig.primaryKey())){
    //                log.debug("默认数据源{}",dataSource.value());
    //            }else {
    //                this.dataSourceConfig.isExistDs(dataSource.value());
    //                log.debug("切换数据源：{}->{}", DataSourceContextHolder.getDataSourceKey(), dataSource.value());
    //                DataSourceContextHolder.setDataSourceKey(dataSource.value());
    //            }
    //        }
    //        try {
    //            return joinPoint.proceed();
    //        }
    //        finally {
    //            // 销毁数据源 在执行方法之后
    //            DataSourceContextHolder.clearDataSourceKey();
    //            log.debug("清除数据源");
    //        }
    //    }
    //    return joinPoint.proceed();
    //}

}
